
package com.compuvest.advert;

// <editor-fold defaultstate="collapsed" desc="import">
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// </editor-fold>

public class GoogleFile extends HttpServlet {
   
// <editor-fold defaultstate="collapsed" desc="init">
    public static Logger log = LoggerFactory.getLogger(GoogleFile.class);

    static String ADVERT_PATH =	null;
    static String SITE_URL = null;

    private boolean DBG = false;

    private File dir;
    private DataSource ds;
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="init()">

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        // set database
        try {
            Context initCtx = new InitialContext();
            ds = (DataSource)initCtx.lookup("jdbc/mysql");
        }
        catch(Exception e) {
            log.error("init(): " + e);
        }

        // set PATH
        SITE_URL = config.getInitParameter("SITE_URL");
        if(SITE_URL == null) {
            log.error("Error SITE_URL is null define in web.xml");
            SITE_URL = "HTTP://URL_LINK_NOT_DEFINED/";
        }
        ADVERT_PATH = config.getInitParameter("ADVERT_PATH");
        if(ADVERT_PATH == null) {
            log.error("Error ADVERT_PATH is null define in web.xml");
            ADVERT_PATH = "/tmp";
        }

        dir = new File(ADVERT_PATH);
        // check saveDirectory is truely a directory
        if(!dir.isDirectory()) {
            log.error("Error " + ADVERT_PATH + " not directory");
        }
        // check saveDirectory is writable
        if(!dir.canWrite()) {
            log.error("GoogleFile init: Error " + ADVERT_PATH + " not writable");
        }

        log.info("GoogleFile::init " + getVersion());
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="processRequest">

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {

        if(request.getParameter("google") != null) {

            response.setContentType("text/xml;charset=UTF-8");

            StringBuilder xml = new StringBuilder();
            xml.append("<?xml version='1.0' encoding='UTF-8'?>");
            xml.append("<status>");
            xml.append("<message1>").append("doGoogleOldCompuvestStock").append("</message1>");

            doGoogleOldCompuvestStock(); // group_id == 50 compuvest old stock

            xml.append("<message2>").append("doGoogleAdvertFile").append("</message2>");

            doGoogleAdvertFile();

            xml.append("<sessionid>").append(request.getSession().getId()).append("</sessionid>");
            xml.append("<code>").append("").append("</code>");
            xml.append("</status>");

            try (PrintWriter out = response.getWriter()) {
                out.print(xml.toString());
            }
        }
    } 
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="getSubcatTable()">

    final static String GETVENDORS =
        "SELECT subcat_id,vendor_id " +
        "FROM advert.googleSend " +
        "WHERE group_id=?";

    private Map<Integer,ArrayList<Integer>> getSubcatTable(int groupid) {

        Map<Integer,ArrayList<Integer>> subcatTable = new HashMap<>();

        try(
            Connection cn = ds.getConnection();
            PreparedStatement  ps = cn.prepareStatement(GETVENDORS))
        {
            ps.setInt(1, groupid);

            try (ResultSet rs = ps.executeQuery()) {
                while(rs.next()) {
                    if(subcatTable.containsKey(rs.getInt("subcat_id"))) {
                        ArrayList<Integer> tempvendors = subcatTable.get(rs.getInt("subcat_id"));
                        tempvendors.add(rs.getInt("vendor_id"));
                    }
                    else {
                        ArrayList<Integer> tempvendors = new ArrayList<>();
                        tempvendors.add(rs.getInt("vendor_id"));
                        subcatTable.put(rs.getInt("subcat_id"), tempvendors);
                    }
                }
            }
        }
        catch(SQLException se) {
            log.error("getSubcatTable(): " + se);
        }

        return subcatTable;
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="getGroups()">

    final static String GETGROUPS =
        "SELECT group_id,name,fileName,cpcmax,cpccont,active " +
        "FROM advert.googleGroups " +
        "WHERE fileName IS NOT NULL";

    private Map<Integer,Groups> getGroups() {

        Map<Integer,Groups> groups = new HashMap<>();

        try(
            Connection cn = ds.getConnection();
            PreparedStatement ps = cn.prepareStatement(GETGROUPS);
            ResultSet rs = ps.executeQuery())
        {
            while(rs.next()) {
                groups.put(rs.getInt("group_id"),
                            new Groups(
                                rs.getInt("group_id"),
				rs.getString("name"),
				rs.getString("fileName"),
				rs.getDouble("cpcmax"),
				rs.getDouble("cpccont"),
				rs.getBoolean("active"))
                );
            }
        }
        catch(SQLException se) {
            log.error("getGroups():\n" + se.getMessage());
        }

        return groups;
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="doGoogleOldCompuvestStock()">
//
// CVS=2, CAS=83, ADV=27, AAA=29
//
    final static String ADGROUPS   = "{1}{0}{2}{0}{3,number,0.00}{0}{4,number,0.00}{0}{5}\r\n";
    final static String ADTEXT     = "{1}{0}{2}{0}{3} on Sale{0}Buy {4} for ${5,number,0.00}{0}Free Ground Shipping{0}http://www.compuvest.com{0}{6}{4}&advsite={7}&sku={2}\r\n";
    final static String ADKEYWORDS = "{1}{0}{2}{0}{3}{0}Exact{0}{4,number,0.00}{0}{5}{3}&advsite={6}&sku={2}\r\n";

    static final String TRUNCATE_ITEMSINUSE = "TRUNCATE TABLE advert.googleUseItems";
    static final String INSERT_ITEMSINUSE = "INSERT INTO advert.googleUseItems SET item_id=?";
    static final String DROP_TEMPORARY = "DROP TEMPORARY TABLE IF EXISTS advert.TEMPA,advert.TEMPB";

    static final String CREATE_TABLE_TEMPA =
        "CREATE TEMPORARY TABLE IF NOT EXISTS advert.TEMPA (" +
        "item_id INT(10)," +
        "category_id INT(10)," +
        "group_id INT(4)," +
        "groups VARCHAR(25)," +
        "cpcmax DOUBLE(10,2)," +
        "cpccont DOUBLE(10,2)," +
        "status BOOLEAN," +
        "accwareCatID VARCHAR(15)," +
        "mfrNumber VARCHAR(30)," +
        "sell_price DOUBLE(10,2)," +
        "conditions VARCHAR(20))";

    static final String CREATE_TABLE_TEMPB =
        "CREATE TEMPORARY TABLE IF NOT EXISTS advert.TEMPB " +
        "SELECT item_id,category_id,group_id,accwareCatID,mfrNumber,sell_price,groups,cpcmax,cpccont,status status,conditions " +
        "FROM advert.TEMPA " +
        "ORDER BY sell_price";

    static final String SELECT_TEMPB =
        "SELECT item_id,category_id,group_id,tb.accwareCatID accwCatID,mfrNumber,sell_price,groups,cpcmax," +
        "cpccont,status status,conditions,ct.alias catName " +
        "FROM advert.TEMPB tb " +
        "LEFT JOIN advert.googleCategory ct USING(category_id) " +
        "WHERE ct.category_id IS NOT NULL " +
        "GROUP BY mfrNumber";
//        "GROUP BY mfrNumber,conditions";

    private void doGoogleOldCompuvestStock() {

        FileOutputStream adgroups = null;
        FileOutputStream adtext = null;
        FileOutputStream keywords = null;
        Map<Integer,Groups> groups = null;

        try(Connection cn = ds.getConnection()) {

            PreparedStatement ps2;

            // clean table
            PreparedStatement ps = cn.prepareStatement(TRUNCATE_ITEMSINUSE);
            ps.executeUpdate();
            ps.close();

            // create TEMP table
            ps = cn.prepareStatement(CREATE_TABLE_TEMPA);
            ps.executeUpdate();
            ps.close();

            groups = getGroups();
            Iterator gkey = groups.keySet().iterator();
            while(gkey.hasNext()) {
                int groupid = (Integer)gkey.next();
                if(groupid != 50) { continue; } // we need old compuvuvest stock

                Groups group = (Groups)groups.get(groupid);

                if(group.getFileGroups() == null) {
//                    System.out.println("group.getGroupsID()="+group.getGroupsID()+"\nadvertsFileName.get(group.getGroupsID())="+advertsFileName.get(group.getGroupsID()));
                    group.setFileGroups(new FileOutputStream(ADVERT_PATH + group.getFileName() +"_adgroups.txt", false));
                    group.setFileText(new FileOutputStream(ADVERT_PATH + group.getFileName() +"_adtext.txt", false));
                    group.setFileKeywords(new FileOutputStream(ADVERT_PATH + group.getFileName() +"_keywords.txt", false));
                }

                Map<Integer,ArrayList<Integer>> subcatTable = getSubcatTable(group.getGroupsID());
                Iterator ens = subcatTable.keySet().iterator();
                while(ens.hasNext()) {
                    int subcatid = (Integer)ens.next();
                    String strven = (String)subcatTable.get(subcatid).toString().replace('[',' ').replace(']',' ');

                    ps = cn.prepareStatement(new StringBuilder(400).
                    append("INSERT INTO advert.TEMPA ").
                    append("(item_id,category_id,accwareCatID,mfrNumber,sell_price,conditions,group_id,groups,cpcmax,cpccont,status) ").
                    append("SELECT it.item_id item_id,it.category_id category_id,it.accwareCatID accwareCatID,ia.mfrNumber mfr_number,it.sell_price sell_price,cs.description conditions,").
                    append("?,?,?,?,? ").
                    append("FROM sklad.items it ").
                    append("LEFT JOIN sklad.itemsAdvert ia USING(item_id) ").
                    append("LEFT JOIN sklad.conditions cs ON LEFT(RIGHT(accwareCatID,2),1)=cs.id ").
                    append("WHERE active='Y' AND category_id=? AND vendor_id=2 "). //AND createTime < DATE_SUB(NOW(), INTERVAL 6 MONTH) older than 6 month
                    append("AND ia.item_id IS NOT NULL ").
                    append("AND it.category_id IN (SELECT subcat_id FROM advert.googleSend WHERE group_id=? AND category_id=? ) ").
                    append("AND (it.sell_price > 20 OR it.vendor_id IN(2,83,27,29)) "). //AND it.stock_quantity > 0
                    append("AND it.vendor_id IN(").append(strven).append(") ORDER BY sell_price").toString());
                    ps.setInt(1, group.getGroupsID());
                    ps.setString(2, group.getName());
                    ps.setDouble(3, group.getCPCMax());
                    ps.setDouble(4, group.getCPCCont());
                    ps.setBoolean(5, group.getStatus());
                    ps.setInt(6, subcatid);
                    ps.setInt(7, group.getGroupsID());
                    ps.setInt(8, subcatid);

                    ps.executeUpdate();
                    ps.close();
                }
            }

            // make sort by price
            ps = cn.prepareStatement(CREATE_TABLE_TEMPB);
            ps.executeUpdate();
            ps.close();

            ps = cn.prepareStatement(SELECT_TEMPB);
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {

                ps2 = cn.prepareStatement(INSERT_ITEMSINUSE);
                ps2.setInt(1, rs.getInt("item_id"));
                ps2.executeUpdate();
                ps2.close();

                Groups group = groups.get(rs.getInt("group_id"));

                adgroups = group.getFileGroups();
                adtext = group.getFileText();
                keywords = group.getFileKeywords();

                adgroups.write(
                MessageFormat.format(ADGROUPS, new Object[] {
/* 0*/          '\t',
/* 1*/          rs.getString("groups"),
/* 2*/          rs.getString("accwCatID"),
/* 3*/          rs.getDouble("cpcmax"),
/* 4*/          rs.getDouble("cpccont"),
/* 5*/          rs.getBoolean("status") ? "Active" : "Deleted"
                }).getBytes());

                adtext.write(
                MessageFormat.format(ADTEXT, new Object[] {
/* 0*/          '\t',
/* 1*/          rs.getString("groups"),
/* 2*/          rs.getString("accwCatID"),
/* 3*/          rs.getString("catName"),
/* 4*/          rs.getString("mfrNumber"),
/* 5*/          rs.getDouble("sell_price"),
/* 6*/          SITE_URL,
/* 7*/          group.getFileName()
                }).getBytes());

                keywords.write(
                MessageFormat.format(ADKEYWORDS, new Object[] {
/* 0*/          '\t',
/* 1*/          rs.getString("groups"),
/* 2*/          rs.getString("accwCatID"),
/* 3*/          rs.getString("mfrNumber"),
/* 4*/          rs.getDouble("cpcmax"),
/* 5*/          SITE_URL,
/* 6*/          group.getFileName()
                }).getBytes());

                group.countItem++;
            }
            rs.close();

            // delete TEMP table
            ps = cn.prepareStatement(DROP_TEMPORARY);
            ps.executeUpdate();
            ps.close();

            // update count
            ps = cn.prepareStatement("UPDATE advert.googleGroups SET itemsCount=? WHERE group_id=50");
            ps.setInt(1, groups.get(50).getCountItem());
            ps.executeUpdate();
            ps.close();
        }
        catch(IOException | SQLException ex) {
            log.error("doGoogleOldCompuvestStock(): " + ex);
        }
        finally {
            // close - opened files
            if(groups != null) {
                Iterator tkeyn = groups.keySet().iterator();
                while(tkeyn.hasNext()) {
                    int groupid = (Integer)tkeyn.next();
                    Groups group = (Groups)groups.get(groupid);
                    group.close();
                }
            }
            if(adgroups != null) {
                try { adgroups.close(); adgroups = null; }  catch(IOException ignore) { }
            }
            if(adtext != null) {
                try { adtext.close(); adtext = null; }      catch(IOException ignore) { }
            }
            if(keywords != null) {
                try { keywords.close(); keywords = null; }  catch(IOException ignore) { }
            }
        }
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="doGoogleAdvertFile()">
/*
SELECT it.item_id item_id,it.category_id category_id,it.accwareCatID accwareCatID,ia.mfrNumber mfr_number,it.sell_price sell_price,cs.description conditions
FROM sklad.items it
LEFT JOIN sklad.itemsAdvert ia USING(item_id)
LEFT JOIN sklad.conditions cs ON LEFT(RIGHT(accwareCatID,2),1)=cs.id
WHERE it.active='Y' AND it.category_id=640 AND ia.item_id IS NOT NULL
AND it.category_id IN (SELECT subcat_id FROM google.advertSend WHERE group_id=81 AND category_id=640)
AND it.vendor_id IN(1,3,8,9) ORDER BY it.sell_price
*/
    private void doGoogleAdvertFile() {

        FileOutputStream adgroups = null;
        FileOutputStream adtext = null;
        FileOutputStream keywords = null;
        Map<Integer,Groups> groups = null;

        try(Connection cn = ds.getConnection()) {

            // create TEMP table
            PreparedStatement ps = cn.prepareStatement(CREATE_TABLE_TEMPA);
            ps.executeUpdate();
            ps.close();

            groups = getGroups();
            Iterator gkey = groups.keySet().iterator();
            while(gkey.hasNext()) {
                int groupid = (Integer)gkey.next();
                if(groupid == 50) { continue; } // old compuvuvest stock

                Groups group = (Groups)groups.get(groupid);

                if(group.getFileGroups() == null) {
                    group.setFileGroups(new FileOutputStream(ADVERT_PATH + group.getFileName() + "_adgroups.txt", false));
                    group.setFileText(new FileOutputStream(ADVERT_PATH + group.getFileName() + "_adtext.txt", false));
                    group.setFileKeywords(new FileOutputStream(ADVERT_PATH + group.getFileName() + "_keywords.txt", false));
                }

                Map<Integer,ArrayList<Integer>> subcatTable = getSubcatTable(group.getGroupsID());
                Iterator ens = subcatTable.keySet().iterator();
                while(ens.hasNext()) {
                    int subcatid = (Integer)ens.next();
                    String strven = (String)subcatTable.get(subcatid).toString().replace('[',' ').replace(']',' ');

                    ps = cn.prepareStatement(new StringBuilder(300).
                    append("INSERT INTO advert.TEMPA ").
                    append("(item_id,category_id,accwareCatID,mfrNumber,sell_price,conditions,group_id,groups,cpcmax,cpccont,status) ").
                    append("SELECT it.item_id item_id,it.category_id category_id,it.accwareCatID accwareCatID,ia.mfrNumber mfr_number,it.sell_price sell_price,cs.description conditions,").
                    append("?,?,?,?,? ").
                    append("FROM sklad.items it ").
                    append("LEFT JOIN sklad.itemsAdvert ia USING(item_id) ").
                    append("LEFT JOIN sklad.conditions cs ON LEFT(RIGHT(accwareCatID,2),1)=cs.id ").
                    append("WHERE it.active='Y' AND it.category_id=? AND ia.item_id IS NOT NULL ").
                    append("AND it.category_id IN (SELECT subcat_id FROM advert.googleSend WHERE group_id=? AND category_id=?) ").
                    append("AND (it.sell_price > 20 OR it.vendor_id IN(2,83,27,29)) ").//AND it.stock_quantity > 0
                    append("AND it.vendor_id IN(").append(strven).append(") ORDER BY it.sell_price").toString());
                    ps.setInt(1, group.getGroupsID());
                    ps.setString(2, group.getName());
                    ps.setDouble(3, group.getCPCMax());
                    ps.setDouble(4, group.getCPCCont());
                    ps.setBoolean(5, group.getStatus());
                    ps.setInt(6, subcatid);
                    ps.setInt(7, group.getGroupsID());
                    ps.setInt(8, subcatid);

                    ps.executeUpdate();
                    ps.close();
                }
                if(groupid == 81){

                }
            }

            // make sort by price
            ps = cn.prepareStatement(CREATE_TABLE_TEMPB);
            ps.executeUpdate();
            ps.close();

            ps = cn.prepareStatement(
                "SELECT item_id,category_id,group_id,tb.accwareCatID accwCatID,mfrNumber,sell_price," +
                "groups,cpcmax,cpccont,status status,conditions,ct.alias catName " +
                "FROM advert.TEMPB tb " +
                "LEFT JOIN advert.googleUseItems iiu USING(item_id) " +
                "LEFT JOIN advert.googleCategory ct USING(category_id) " +
                "WHERE iiu.item_id IS NULL AND ct.category_id IS NOT NULL " +
                "GROUP BY mfrNumber");
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {
                Groups group = groups.get(rs.getInt("group_id"));

                adgroups = group.getFileGroups();
                adtext = group.getFileText();
                keywords = group.getFileKeywords();

                adgroups.write(
                MessageFormat.format(ADGROUPS, new Object[] {
/* 0*/          '\t',
/* 1*/          rs.getString("groups"),
/* 2*/          rs.getString("accwCatID"),
/* 3*/          rs.getDouble("cpcmax"),
/* 4*/          rs.getDouble("cpccont"),
/* 5*/          rs.getBoolean("status")  ? "Active" : "Deleted"
                }).getBytes());

                adtext.write(
                MessageFormat.format(ADTEXT, new Object[] {
/* 0*/          '\t',
/* 1*/          rs.getString("groups"),
/* 2*/          rs.getString("accwCatID"),
/* 3*/          rs.getString("catName"),
/* 4*/          rs.getString("mfrNumber"),
/* 5*/          rs.getDouble("sell_price"),
/* 6*/          SITE_URL,
/* 7*/          group.getFileName()
                }).getBytes());

                keywords.write(
                MessageFormat.format(ADKEYWORDS, new Object[] {
/* 0*/          '\t',
/* 1*/          rs.getString("groups"),
/* 2*/          rs.getString("accwCatID"),
/* 3*/          rs.getString("mfrNumber"),
/* 4*/          rs.getDouble("cpcmax"),
/* 5*/          SITE_URL,
/* 6*/          group.getFileName()
                }).getBytes());

                group.countItem++;
            }
            rs.close();

            // delete TEMP table
            ps = cn.prepareStatement(DROP_TEMPORARY);
            ps.executeUpdate();
            ps.close();

            // update count
            ps = cn.prepareStatement("UPDATE advert.googleGroups SET itemsCount=? WHERE group_id=?");
            gkey = groups.keySet().iterator();
            while(gkey.hasNext()) {
                int groupid = (Integer)gkey.next();
                if(groupid == 50) { continue; } // old compuvuvest stock

                ps.setInt(1, groups.get(groupid).getCountItem());
                ps.setInt(2, groupid);
                ps.addBatch();
            }
            ps.executeBatch();
            ps.close();
    	}
        catch(IOException | SQLException ex) {
            log.error("doGoogleAdvertFile(): " + ex);
        }
        finally {
            // close - opened files
            if(groups != null) {
                Iterator gkey = groups.keySet().iterator();
                while(gkey.hasNext()) {
                    int groupid = (Integer)gkey.next();
                    Groups group = (Groups)groups.get(groupid);
                    group.close();
                }
            }
            if(adgroups != null) {
                try { adgroups.close(); adgroups = null; }  catch(IOException ignore) { }
            }
            if(adtext != null) {
                try { adtext.close(); adtext = null; }      catch(IOException ignore) { }
            }
            if(keywords != null) {
                try { keywords.close(); keywords = null; }  catch(IOException ignore) { }
            }
        }
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="getVersion()">

      private String getVersion() {

        String result = "";
        try(Connection cn = ds.getConnection();
            PreparedStatement ps = cn.prepareStatement("SELECT VERSION() ver");
            ResultSet rs = ps.executeQuery())
        {
            if(rs.next()) {
                result = rs.getString("ver");
            }
        }
        catch(SQLException se) {
            log.error("getVersion(): " + se);
        }

        return result;
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="HttpServlet methods.">

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
        processRequest(request, response);
    } 

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public void destroy() {
        ds = null;

        log.info("Destroy:");
    }

    @Override
    public String getServletInfo() {
        return "GoogleFile";
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="class Groups()">

    class Groups {

        private int groups_id;
        private int countItem;
        private String name;
        private String fileName;
        private double cpcmax;
        private double cpccont;
        private boolean status;

        private FileOutputStream filegroups;
        private FileOutputStream filetext;
        private FileOutputStream filekeywords;

        public Groups() {
            this(0, "", "not_set_google_file", 0d, 0d, false);
        }

        public Groups(int groups_id, String name, String fileName, double cpcmax, double cpccont, boolean status) {
            this.groups_id = groups_id;
            this.name = name;
            this.fileName = fileName;
            this.cpcmax = cpcmax;
            this.cpccont = cpccont;
            this.status = status;
            this.filegroups = null;
            this.filetext = null;
            this.filekeywords = null;
            this.countItem = 0;
        }

        public int getGroupsID()    { return groups_id; }
        public String getName()     { return name; }
        public String getFileName() { return fileName; }
        public double getCPCMax()   { return cpcmax; }
        public double getCPCCont()  { return cpccont; }
        public boolean getStatus()  { return status; }

        public int getCountItem()                               { return countItem; }
        public void setCountItem(int count)                     { this.countItem = count; }

    	public FileOutputStream getFileGroups()                 { return filegroups; }
        public void setFileGroups(FileOutputStream groups)      { this.filegroups = groups; }

        public FileOutputStream getFileText()                   { return filetext; }
        public void setFileText(FileOutputStream text)		{ this.filetext = text; }

        public FileOutputStream getFileKeywords()               { return filekeywords; }
        public void setFileKeywords(FileOutputStream keywords)	{ this.filekeywords = keywords; }

        public void close() {
            if(filegroups != null) {
                try { filegroups.close();   filegroups = null; }    catch(IOException ignore) { }
            }
            if(filetext != null) {
                try { filetext.close();     filetext = null; }      catch(IOException ignore) { }
            }
            if(filekeywords != null) {
                try { filekeywords.close(); filekeywords = null; }  catch(IOException ignore) { }
            }
        }
    }
// </editor-fold>

}
